package web

import (
	"fmt"
	regexp "github.com/dlclark/regexp2"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
	"webook/internal/domain"
	"webook/internal/service"
)

type UserHandler struct {
	svc         *service.UserService
	emailExp    *regexp.Regexp
	passwordExp *regexp.Regexp
	birthdayExp *regexp.Regexp
}

func NewUserHandler(svc *service.UserService) *UserHandler {
	const (
		emailRegexPattern    = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"
		passwordRegexPattern = `^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$`
		birthdayRegexPattern = `^\d{4}-\d{2}-\d{2}$`
	)
	emailExp := regexp.MustCompile(emailRegexPattern, regexp.None)
	passwordExp := regexp.MustCompile(passwordRegexPattern, regexp.None)
	birthdayExp := regexp.MustCompile(birthdayRegexPattern, regexp.None)
	return &UserHandler{
		svc:         svc,
		emailExp:    emailExp,
		passwordExp: passwordExp,
		birthdayExp: birthdayExp,
	}
}

func (u *UserHandler) RegisterRoutes(server *gin.Engine) {
	ug := server.Group("/users")  //ug is user group
	ug.GET("/profile", u.Profile) // 查询用户信息接口
	ug.POST("/signup", u.SignUp)  // 注册接口
	ug.POST("/login", u.Login)    // 登录接口
	ug.POST("/logout", u.Logout)  // 登出接口
	ug.POST("/edit", u.Edit)      // 修改用户信息接口

}

func (u *UserHandler) RegisterRoutesV1(ug *gin.RouterGroup) {
	ug.GET("/profile", u.Profile) // 查询用户信息接口
	ug.POST("/signup", u.SignUp)  // 注册接口
	ug.POST("/login", u.Login)    // 登录接口
	ug.POST("/logout", u.Logout)  // 登出接口
	ug.POST("/edit", u.Edit)      // 修改用户信息接口

}
func (u *UserHandler) Profile(ctx *gin.Context) {
	type ProfileRequest struct{}
	var request ProfileRequest
	// 通过session 拿到userId
	sess := sessions.Default(ctx)
	userId := sess.Get("userId")
	// 将id转换成int64
	idInt64, _ := userId.(int64)
	// 调用以一下svc 的方法
	user, err := u.svc.Profile(ctx, idInt64)
	if err := ctx.Bind(&request); err != nil {
		return
	}
	var userinfo map[string]interface{}
	userinfo = make(map[string]interface{})
	userinfo["id"] = user.Id
	userinfo["email"] = user.Email
	userinfo["nickname"] = user.Nickname
	userinfo["birthday"] = user.Birthday
	userinfo["introduction"] = user.Introduction
	userinfo["createdAt"] = user.Ctime
	fmt.Println(userinfo)
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}
	ctx.String(http.StatusOK, "查询成功", "/n/r userinfo: %v", userinfo)
}

func (u *UserHandler) SignUp(ctx *gin.Context) {
	type SignUpRequest struct {
		Email           string `json:"email"`
		Password        string `json:"password"`
		ConfirmPassword string `json:"confirmPassword"`
	}
	var request SignUpRequest
	// 如果 Bind 方法发现输入有问题，它就会直接返回一 个错误响应到前端。
	if err := ctx.Bind(&request); err != nil {
		return
	}

	ok, err := u.emailExp.MatchString(request.Email)
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}
	if !ok {
		ctx.String(http.StatusOK, "邮箱格式错误")
		return
	}
	ok, err = u.passwordExp.MatchString(request.Password)
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}
	if !ok {
		ctx.String(http.StatusOK, "密码必须包含至少一个数字、一个字母、一个特殊字符，并且长度至少为8位")
		return
	}
	if request.Password != request.ConfirmPassword {
		ctx.String(http.StatusOK, "两次密码不一致")
		return
	}
	// 调用以一下svc 的方法
	err = u.svc.SignUp(ctx, domain.User{
		Email:    request.Email,
		Password: request.Password,
	})
	if err == service.ErrUserDuplicateEmail {
		ctx.String(http.StatusOK, "邮箱冲突")
		return
	}
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return

	}
	ctx.String(http.StatusOK, "注册成功")
}
func (u *UserHandler) Login(ctx *gin.Context) {
	type LoginRequest struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	var request LoginRequest
	if err := ctx.Bind(&request); err != nil {
		return
	}
	// 调用以一下svc 的方法
	user, err := u.svc.Login(ctx, request.Email, request.Password)

	if err == service.ErrInvalidUserOrPassword {
		ctx.String(http.StatusOK, "账号或密码错误")
		return
	}
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}
	// 登录成功设置session
	sess := sessions.Default(ctx)
	// 设置session的key和value
	sess.Set("userId", user.Id)
	sess.Save()
	ctx.String(http.StatusOK, "登录成功")
	return
}

func (u *UserHandler) Logout(ctx *gin.Context) {
}
func (u *UserHandler) Edit(ctx *gin.Context) {
	type EditRequest struct {
		Nickname     string `json:"nickname"`
		Birthday     string `json:"birthday"`
		Introduction string `json:"introduction"`
	}
	var request EditRequest
	if err := ctx.Bind(&request); err != nil {
		return
	}

	if request.Nickname != "" && len(request.Nickname) > 10 {
		ctx.String(http.StatusOK, "昵称长度不能超过10个字符")
		return
	}
	// 处理时间格式
	if request.Birthday != "" {
		ok, _ := u.birthdayExp.MatchString(request.Birthday)
		if !ok {
			ctx.String(http.StatusOK, "生日格式错误")
			return
		}
	}
	// 处理个人介绍字符长度不能超过50
	if request.Introduction != "" && len(request.Introduction) > 50 {
		ctx.String(http.StatusOK, "个人介绍长度不能超过50个字符")
		return
	}
	// 通过session 拿到userId
	sess := sessions.Default(ctx)
	userId := sess.Get("userId")

	// 将id转换成int64
	idInt64, _ := userId.(int64)
	// 调用以一下svc 的方法
	err := u.svc.Edit(ctx, domain.User{
		Id:           idInt64,
		Nickname:     request.Nickname,
		Birthday:     request.Birthday,
		Introduction: request.Introduction,
	})
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}
	ctx.String(http.StatusOK, "修改成功")
}
